(define (to-bignum radix smlnum)
  (define (to-bn sn)
    (cond
      ((zero? sn) '(0))
      (else
       (let* ((bn (to-bn (quotient sn radix))))
         (cons (+ (car bn) 1) (cons (remainder sn radix) (cdr bn))) ) ) ) )
  (cond
    ((negative? smlnum)
     (let ((bn (to-bn (- smlnum))))
       (cons (- (car bn)) (cdr bn)) ) )
    (else (to-bn smlnum)) ) )

(define (from-bignum radix bignum)
  (define (from-bn ds)
    (cond
      ((null? ds) 0)
      (else (+ (car ds) (* radix (from-bn (cdr ds)))) ) ) )
  (let ((nd (car bignum)))
    (cond
      ((zero? nd) 0)
      ((negative? nd) (- (from-bn (cdr bignum))))
      (else (from-bn (cdr bignum))) ) ) )

(define (bignum-absolute bn)
  (cons (abs (car bn)) (cdr bn)) )

(define (bignum-negate bn)
  (cons (- (car bn)) (cdr bn)) )

(define (bignum-zero? bn)
  (zero? (car bn)) )

(define (bignum-positive? bn)
  (positive? (car bn)) )

(define (bignum-negative? bn)
  (negative? (car bn)) )

(define (bignum-even? bn)
  (or (zero? (car bn)) (even? (cadr bn))) )

(define (bignum-odd? bn)
  (and (not (zero? (car bn))) (odd? (cadr bn))) )

(define (bignum-compare bn1 bn2)
  (let ((nd1 (car bn1))
        (nd2 (car bn2)) )
    (cond
      ((< nd1 nd2) -1)
      ((> nd1 nd2) 1)
      ((zero? nd1) 0)
      (else
       (let dwise ((ds1 (reverse (cdr bn1)))
                   (ds2 (reverse (cdr bn2))) )
         (if (null? ds1)
             0
             (let ((d1 (car ds1))
                   (d2 (car ds2)) )
               (cond
                 ((< d1 d2) (if (positive? nd1) -1 1))
                 ((> d1 d2) (if (positive? nd2) 1 -1))
                 (else (dwise (cdr ds1) (cdr ds2))) ) ) ) ) ) ) ) )

(define (bignum-eq? bn1 bn2)
  (zero? (bignum-compare bn1 bn2)) )

(define (bignum-ne? bn1 bn2)
  (not (zero? (bignum-compare bn1 bn2))) )
 
(define (bignum-lt? bn1 bn2)
  (negative? (bignum-compare bn1 bn2)) )

(define (bignum-gt? bn1 bn2)
  (positive? (bignum-compare? bn2 bn1)) )

(define (bignum-le? bn1 bn2)
  (not (positive? (bignum-compare bn1 bn2))) )

(define (bignum-ge? bn1 bn2)
  (not (negative? (bignum-compare bn1 bn2))) )

